package com.yunji.news.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yunji.news.entity.SystemConfig;
import com.yunji.news.mapper.SystemConfigMapper;
import com.yunji.news.service.SystemConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 系统配置服务实现类
 *
 * @author yunji
 * @since 2024-11-25
 */
@Service
@Slf4j
public class SystemConfigServiceImpl extends ServiceImpl<SystemConfigMapper, SystemConfig> implements SystemConfigService {

    /**
     * 配置缓存
     */
    private final Map<String, String> configCache = new ConcurrentHashMap<>();

    @PostConstruct
    public void init() {
        // 初始化时加载所有配置到缓存
        refreshCache();
    }

    @Override
    public Page<SystemConfig> getConfigPage(Page<SystemConfig> page, String configGroup, String configKey) {
        LambdaQueryWrapper<SystemConfig> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.hasText(configKey), SystemConfig::getConfigKey, configKey)
                .eq(StringUtils.hasText(configGroup), SystemConfig::getConfigGroup, configGroup)
                .eq(SystemConfig::getDeleted, 0)
                .orderByAsc(SystemConfig::getConfigGroup)
                .orderByAsc(SystemConfig::getSortOrder)
                .orderByAsc(SystemConfig::getConfigKey);

        return this.page(page, wrapper);
    }

    @Override
    public String getConfigValue(String configKey) {
        return getConfigValue(configKey, null);
    }

    @Override
    public String getConfigValue(String configKey, String defaultValue) {
        if (!StringUtils.hasText(configKey)) {
            return defaultValue;
        }

        // 优先从缓存获取
        String value = configCache.get(configKey);
        if (value != null) {
            return value;
        }

        // 缓存中没有，从数据库获取
        value = baseMapper.selectValueByKey(configKey);
        if (value != null) {
            configCache.put(configKey, value);
            return value;
        }

        return defaultValue;
    }

    @Override
    public List<SystemConfig> getConfigsByGroup(String configGroup) {
        return baseMapper.selectByGroup(configGroup);
    }

    @Override
    public Map<String, String> getConfigMapByGroup(String configGroup) {
        List<SystemConfig> configs = getConfigsByGroup(configGroup);
        return configs.stream()
                .collect(Collectors.toMap(
                        SystemConfig::getConfigKey,
                        config -> config.getConfigValue() != null ? config.getConfigValue() : "",
                        (existing, replacement) -> existing
                ));
    }

    @Override
    public List<String> getConfigGroups() {
        return baseMapper.selectGroups();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveOrUpdateConfig(SystemConfig systemConfig) {
        // 检查配置键是否已存在
        if (systemConfig.getId() == null) {
            LambdaQueryWrapper<SystemConfig> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SystemConfig::getConfigKey, systemConfig.getConfigKey())
                    .eq(SystemConfig::getDeleted, 0);
            SystemConfig existingConfig = this.getOne(wrapper);
            if (existingConfig != null) {
                log.warn("配置键已存在: {}", systemConfig.getConfigKey());
                return false;
            }
        }

        // 设置默认值
        if (systemConfig.getStatus() == null) {
            systemConfig.setStatus(1);
        }
        if (systemConfig.getEditable() == null) {
            systemConfig.setEditable(1);
        }
        if (systemConfig.getSortOrder() == null) {
            systemConfig.setSortOrder(0);
        }

        boolean success = this.saveOrUpdate(systemConfig);
        if (success) {
            // 更新缓存
            configCache.put(systemConfig.getConfigKey(), 
                    systemConfig.getConfigValue() != null ? systemConfig.getConfigValue() : "");
        }
        return success;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchUpdateConfigs(List<SystemConfig> configs) {
        boolean success = this.updateBatchById(configs);
        if (success) {
            // 批量更新缓存
            for (SystemConfig config : configs) {
                configCache.put(config.getConfigKey(), 
                        config.getConfigValue() != null ? config.getConfigValue() : "");
            }
        }
        return success;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteConfig(Long id) {
        SystemConfig config = this.getById(id);
        if (config != null && config.getEditable() != null && config.getEditable() == 0) {
            log.warn("不可编辑的配置不能删除: {}", config.getConfigKey());
            return false;
        }

        boolean success = this.removeById(id);
        if (success && config != null) {
            // 从缓存中移除
            configCache.remove(config.getConfigKey());
        }
        return success;
    }

    @Override
    public void refreshCache() {
        try {
            configCache.clear();
            
            LambdaQueryWrapper<SystemConfig> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SystemConfig::getStatus, 1)
                    .eq(SystemConfig::getDeleted, 0);
            
            List<SystemConfig> configs = this.list(wrapper);
            for (SystemConfig config : configs) {
                configCache.put(config.getConfigKey(), 
                        config.getConfigValue() != null ? config.getConfigValue() : "");
            }
            
            log.info("配置缓存刷新成功，共加载{}个配置项", configCache.size());
        } catch (Exception e) {
            log.error("配置缓存刷新失败", e);
        }
    }
}